package com.yunhe.merchants.service.impl;

import com.alibaba.fastjson.JSON;
import com.yunhe.common.constant.OfficeConts;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.exception.ModelNotFoundException;
import com.yunhe.common.exception.ObjectNotFoundException;
import com.yunhe.common.exception.UniqueConstraintsException;
import com.yunhe.common.model.ResultObject;
import com.yunhe.common.model.authority.Organization;
import com.yunhe.common.model.company.ContractAccessories;
import com.yunhe.common.util.DateTimeUtils;
import com.yunhe.common.util.RedisClient;
import com.yunhe.common.util.StringUtil;
import com.yunhe.common.utils.AliOssApiUtils;
import com.yunhe.merchants.client.AuthorityClient;
import com.yunhe.merchants.constant.MyProjectConsts;
import com.yunhe.merchants.domain.*;
import com.yunhe.merchants.repository.ProcessStatusRepository;
import com.yunhe.merchants.service.*;
import com.yunhe.common.util.CollectionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Author: DongWenYu
 * @Date: 2021/5/7 21:19
 */
@Service
public class ProcessStatusServiceImpl implements IProcessStatusService {

    private static final Logger logger = LoggerFactory.getLogger(ProcessStatusServiceImpl.class);

    @Autowired
    ProcessStatusRepository processStatusRepository;

    @Resource(name = "myProjectServiceImpl")
    IMyProjectService myProjectService;

    @Autowired
    IHistoryProjectService historyProjectService;

    @Autowired
    ISuccessProjectService successProjectService;

    @Autowired
    IDataHistoryProjectStatusService dataHistoryProjectStatusService;

    @Autowired
    IDataProjectService dataProjectService;

    @Autowired
    IDataPlanProjectService dataPlanProjectService;

    @Autowired
    RedisClient redisClient;

    @Autowired
    AuthorityClient authorityClient;

    @Override
    public void update(ProcessStatus processStatus , Long id , Long userId) throws ArgumentErrorException, UniqueConstraintsException, ModelNotFoundException, ObjectNotFoundException {
        MyProject myProject = myProjectService.selectById(id);
        //是否回敲
        if(MyProjectConsts.COMPANY_STATUS.Phone.value().equals(processStatus.getStatus()) ||
                MyProjectConsts.COMPANY_STATUS.Visit.value().equals(processStatus.getStatus())){
            if(!StringUtil.isEmpty(myProject.getFirstSource())){
                dataPlanProjectService.updateKnockBackStatusById(myProject.getFirstSource());
            }
        }
        if (MyProjectConsts.BOOLEAN.Yes.value().equals(processStatus.getTelFail())){
            //沟通失败，变为历史项目，状态为失败项目
            telFail( myProject, processStatus ,userId);
        }else if (MyProjectConsts.COMPANY_STATUS.License.value().equals(processStatus.getStatus())){
            if (MyProjectConsts.BOOLEAN.Yes.value().equals(processStatus.getPayoff())){
                //交付尾款，厂房状态变为已租
                myProject.setChosenOffice(processStatus.getChosenOffice());
                setOfficeBooked(myProject,processStatus,userId,"03");
            }
            //证照办理点提交，洽谈项目变为成功项目
            covertToSuccessAndUpdate(myProject,processStatus,userId);
        }else {
            if (MyProjectConsts.COMPANY_STATUS.Sign.value().equals(processStatus.getStatus())){
                myProject.setChosenOffice(processStatus.getChosenOffice());
                setOfficeBooked(myProject,processStatus,userId,"02");
            }
            if (MyProjectConsts.COMPANY_STATUS.Visit.value().equals(processStatus.getStatus())
                    && !StringUtil.isEmpty(processStatus.getVisitPhoto())){
                //如果是现场来访且上传了照片，记录上传照片的时间，开启三个月保护期倒计时
                if(MyProjectConsts.BOOLEAN.Yes.value().equals(processStatus.getStartProtect())){
                    processStatus.setStartProtect(MyProjectConsts.BOOLEAN.Yes.value());
                    processStatus.setStartTime(new Date());
                    myProject.setProtectDate(new Date());
                }
            }
            //状态id与项目id为多对一的关系
            List<ProcessStatus> statusById = processStatusRepository.selectByProjectId(id);
            if (CollectionUtil.isEmpty(statusById)){
                //说明该项目目前还没有状态
//                if (MyProjectConsts.COMPANY_STATUS.Visit.value().equals(processStatus.getStatus())
//                       && !StringUtil.isEmpty(processStatus.getVisitPhoto())){
//                    //如果是现场来访且上传了照片，记录上传照片的时间，开启三个月保护期倒计时
//                    if(MyProjectConsts.BOOLEAN.Yes.value().equals(processStatus.getStartProtect())){
//                        processStatus.setStartProtect(MyProjectConsts.BOOLEAN.Yes.value());
//                        processStatus.setStartTime(new Date());
//                        myProject.setProtectDate(new Date());
//                    }
//                }
                beforeInsert(processStatus,myProject);
                processStatusRepository.insert(processStatus);
            }else {
                ProcessStatus statusByIntentionIdAndStatus = processStatusRepository.selectByProjectIdAndStatus(id, processStatus.getStatus());
                if (statusByIntentionIdAndStatus == null){
                    //如果是新的流程状态的话,就插入新的
                    beforeInsert(processStatus,myProject);
                    processStatusRepository.insert(processStatus);
                }else {
                    //否则就更新老的
                    processStatus.setId(statusByIntentionIdAndStatus.getId());
                    processStatusRepository.update(processStatus);
                }
            }

            //检查有没有推荐厂房重复撞车
            if(MyProjectConsts.COMPANY_STATUS.Visit.value().equals(processStatus.getStatus()) ||
                    MyProjectConsts.COMPANY_STATUS.Phone.value().equals(processStatus.getStatus())||
                    MyProjectConsts.COMPANY_STATUS.FollowUp.value().equals(processStatus.getStatus())){
                if(MyProjectConsts.BOOLEAN.No.value().equals(processStatus.getTelFail())){
                    checkExistOffice(myProject,processStatus.getRecommendOffice());
                }
            }

            //更新项目内容
            if (processStatus.getRecommendOffice() != null){
                myProject.setRecommendOffice(processStatus.getRecommendOffice());
            }
            myProject.setSignTime(processStatus.getSignTime());
            myProject.setExpireTime(processStatus.getExpireTime());
            myProject.setCompanyStatus(processStatus.getStatus());
            myProjectService.update(myProject,userId);
        }
        //更新历史状态
        dataHistoryProjectStatusService.insert(processStatus , myProject);
    }

    private void setOfficeBooked(MyProject myProject, ProcessStatus processStatus, Long userId,String stauts) throws ArgumentErrorException, ModelNotFoundException {
        ResponseEntity<ResultObject> responseEntity = authorityClient.setOfficeStatus(myProject.getId(), myProject.getChosenOffice(), myProject.getCompanyName(), stauts);
        if(responseEntity != null){
            if(responseEntity.getStatusCode().is2xxSuccessful()){
                Object results = responseEntity.getBody().getResults();
                if(results != null){
                    if(results.toString().contains("error")){
                        throw new ArgumentErrorException(results.toString().split("-")[1]);
                    }
//                    else {
//                        if(OfficeConts.OFFICE_STATUS_CODE.Booking.value().equals(stauts)){
//                            //检查有没有推荐厂房重复撞车
//                            if(MyProjectConsts.BOOLEAN.No.value().equals(processStatus.getTelFail())){
//                                checkExistOffice(myProject);
//                            }
//                            //更新项目内容
//                            if (processStatus.getRecommendOffice() != null){
//                                myProject.setRecommendOffice(processStatus.getRecommendOffice());
//                            }
//                            myProject.setSignTime(processStatus.getSignTime());
//                            myProject.setExpireTime(processStatus.getExpireTime());
//                            myProject.setCompanyStatus(processStatus.getStatus());
//                            myProjectService.update(myProject,userId);
//                        }
//                    }
                }
            }
        }

    }

    public void getFile(String filePath,ContractAccessories contractAccessories) throws ArgumentErrorException {
        File file = new File(filePath);
        //判断文件是否存在
        if (!file.exists()) {
            throw new ArgumentErrorException("文件不存在！");
        }
        //获取文件文名
        String fileName = file.getName();
        String s = AliOssApiUtils.putObjectByte(file);
        contractAccessories.setAccessories(s);
        contractAccessories.setAccessoriesName(fileName);
        contractAccessories.setContractName(fileName);
    }

    /**
     * 转化为成功项目并更新
     * @param myProject 
     * @param processStatus 
     * @param userId
     * @return void 
     * @create 2021/5/13 13:38
     */
    private void covertToSuccessAndUpdate(MyProject myProject, ProcessStatus processStatus, Long userId) throws UniqueConstraintsException, ObjectNotFoundException, ArgumentErrorException {
        //成功项目录入在园项目
        List<ContractAccessories> contractAccessoriesList = new ArrayList<>();
        ProcessStatus signProcessStatus = processStatusRepository.selectByProjectIdAndStatus(myProject.getId(), MyProjectConsts.COMPANY_STATUS.Sign.value());
        if(signProcessStatus != null){
            String contract = signProcessStatus.getContract();
            if(!StringUtil.isEmpty(contract)){
                String[] split = contract.split(",");
                for (String s : split) {
                    ContractAccessories contractAccessories = new ContractAccessories();
                    contractAccessories.setContractor(String.valueOf(myProject.getPrincipal()));
                    contractAccessories.setContractSignDate(DateTimeUtils.parseStrToNewStr(DateTimeUtils.PATTERN.DATETIME.value(),
                            signProcessStatus.getCreateTime(),DateTimeUtils.PATTERN.DATE.value()));
                    contractAccessories.setContractPeriodStart(DateTimeUtils.parseStrToNewStr(DateTimeUtils.PATTERN.DATETIME.value(),
                            myProject.getSignTimeStr(),DateTimeUtils.PATTERN.DATE.value()));
                    contractAccessories.setContractPeriodEnd(DateTimeUtils.parseStrToNewStr(DateTimeUtils.PATTERN.DATETIME.value(),
                            myProject.getExpireTimeStr(),DateTimeUtils.PATTERN.DATE.value()));
                    getFile(s,contractAccessories);
                    contractAccessoriesList.add(contractAccessories);
                }
            }
        }
        ResponseEntity<ResultObject<String>> responseEntity = authorityClient.intentionToCompany(myProject.getId(),
                String.valueOf(myProject.getChosenOffice()),
                myProject.getCompanyName(),
                myProject.getSignTimeStr(),
                myProject.getExpireTimeStr(),
                contractAccessoriesList);
        if(responseEntity.getStatusCode().is2xxSuccessful()){
            Object results = responseEntity.getBody().getResults();
            if(results != null){
                if(results.toString().contains("error")){
                    throw new ArgumentErrorException(results.toString().split("-")[1]);
                }else {
                    //更新项目
                    myProject.setCompanyStatus(MyProjectConsts.COMPANY_STATUS.Success.value());
                    myProject.setChosenOffice(processStatus.getChosenOffice());
//        myProject.setExpireTime(processStatus.getExpireTime());
//        myProject.setSignTime(processStatus.getSignTime());
                    myProject.setProtectRemind(MyProjectConsts.BOOLEAN.No.value());
                    myProject.setProtectDate(null);
                    myProjectService.update(myProject, userId);
                    ProcessStatus processStatusOld = processStatusRepository.selectByProjectIdAndStatus(myProject.getId(), MyProjectConsts.COMPANY_STATUS.License.value());
                    if(processStatusOld != null){
                        BeanUtils.copyProperties(processStatusOld,processStatus);
                        processStatus.setId(null);
                    }
                    //更新流程
                    processStatus.setStatus(MyProjectConsts.COMPANY_STATUS.Success.value());
                    beforeInsert(processStatus, myProject);
                    processStatusRepository.insert(processStatus);
                }
            }
        }

    }

    /**
     * 插入流程的前置操作，需要赋给流程组织id和负责人id
     * @param processStatus 
     * @param myProject
     * @return void 
     * @create 2021/5/13 11:21
     */
    private void beforeInsert(ProcessStatus processStatus, MyProject myProject) {
        processStatus.setProjectId(myProject.getId());
        processStatus.setOrgId(myProject.getResponsibleDept());
        processStatus.setPrincipal(myProject.getPrincipal());
    }


    /**
     * 检查是否有推荐厂房撞车并更新
     * @param myProject
     * @return void 
     * @create 2021/5/11 17:45
     */
    private void checkExistOffice(MyProject myProject,Long recommendOffice) {
        if(myProject.getRecommendOffice() != null){
            if(myProject.getRecommendOffice().longValue() != recommendOffice.longValue()){
                List<MyProject> myProjects = myProjectService.selectOtherOfficeByProjectId(myProject.getId());
                if(myProjects.size()==1){
                    for (MyProject project : myProjects) {
                        project.setExistOffice(MyProjectConsts.BOOLEAN.No.value());
                        myProjectService.update(project);
                    }
                }
                checkNewOffice(myProject,recommendOffice);
            }else {
                checkNewOffice(myProject,recommendOffice);
            }
        }else {
            checkNewOffice(myProject,recommendOffice);
        }

    }
    private void checkNewOffice(MyProject myProject,Long recommendOffice){
        myProject.setRecommendOffice(recommendOffice);
        myProjectService.update(myProject);
        List<MyProject> myProjects = myProjectService.selectOtherOfficeByProjectId(myProject.getId());
        if (CollectionUtil.isNotEmpty(myProjects)){
            for (MyProject project : myProjects) {
                project.setExistOffice(MyProjectConsts.BOOLEAN.Yes.value());
                myProjectService.update(project);
            }
            myProject.setExistOffice(MyProjectConsts.BOOLEAN.Yes.value());
        }else {
            myProject.setExistOffice(MyProjectConsts.BOOLEAN.No.value());
        }
    }
    /**
     * 沟通失败
     * @param myProject
     * @param processStatus
     * @return void 
     * @create 2021/5/11 17:45
     */
    private void telFail(MyProject myProject , ProcessStatus processStatus , Long userId) throws ModelNotFoundException, ArgumentErrorException {
        if(myProject.getChosenOffice() != null){
            authorityClient.setOfficeStatus(myProject.getId(),myProject.getChosenOffice(),myProject.getCompanyName(),"01");
        }
        //改变项目状态，写入失败原因
        MyProject project = covertToHistoryAndUpdate(myProject, processStatus ,userId);

        //插入一个失败的流程
        failStatus(processStatus);
        beforeInsert(processStatus,myProject);
        processStatusRepository.insert(processStatus);

        checkTelFailExistOffice(myProject,processStatus.getRecommendOffice());
        //回到经理项目池
        dataProjectService.back(project,MyProjectConsts.DATA_TYPE.ManagerProjectPool.value());
    }

    private void checkTelFailExistOffice(MyProject myProject, Long recommendOffice) {
        if(myProject.getRecommendOffice() != null){
            if(recommendOffice ==null){
                recommendOffice = myProject.getRecommendOffice();
            }
            if(myProject.getRecommendOffice().longValue() != recommendOffice.longValue()){
                List<MyProject> myProjects = myProjectService.selectOtherOfficeByProjectId(myProject.getId());
                if(myProjects.size()==1){
                    for (MyProject project : myProjects) {
                        project.setExistOffice(MyProjectConsts.BOOLEAN.No.value());
                        myProjectService.update(project);
                    }
                }
                //checkNewOffice(myProject,recommendOffice);
            }else {
                checkTelFailNewOffice(myProject,recommendOffice);
            }
        }

    }

    private void checkTelFailNewOffice(MyProject myProject, Long recommendOffice) {
        List<MyProject> myProjects = myProjectService.selectOtherOfficeByProjectId(myProject.getId());
        if(myProjects.size()==1){
            for (MyProject project : myProjects) {
                project.setExistOffice(MyProjectConsts.BOOLEAN.No.value());
                myProjectService.update(project);
            }
        }
    }

    /**
     * 失败后意向项目转为历史项目
     * @param myProject
     * @param processStatus
     * @return com.yunhe.merchants.domain.HistoryProject 
     * @create 2021/5/11 17:45
     */
    private MyProject covertToHistoryAndUpdate(MyProject myProject , ProcessStatus processStatus , Long userId) {
        //转化为historyProject
        myProject.setCompanyStatus(MyProjectConsts.COMPANY_STATUS.Fail.value());
        myProject.setFailureCause(processStatus.getFailReason());
        myProject.setProtectDate(null);
        myProject.setProtectRemind(MyProjectConsts.BOOLEAN.No.value());
        myProject.setExistOffice(MyProjectConsts.BOOLEAN.No.value());
        myProjectService.update(myProject,userId);
        return myProject;
    }

    /**
     * 单击下一步，更新到下一个状态。
     * @param id 
     * @param userId
     * @return void 
     * @create 2021/5/10 11:19
     */
    @Override
    public void next(Long id, Long userId) throws ArgumentErrorException {
        //项目更新状态
        MyProject myProject = myProjectService.selectById(id);
        if (Integer.parseInt(myProject.getCompanyStatus()) < Integer.parseInt(MyProjectConsts.COMPANY_STATUS.License.value())){
            myProject.setCompanyStatus(String.valueOf(Integer.parseInt(myProject.getCompanyStatus())+1));
            myProjectService.update(myProject,userId);
            //是否回敲
            if(MyProjectConsts.COMPANY_STATUS.Phone.value().equals(myProject.getCompanyStatus()) ||
                    MyProjectConsts.COMPANY_STATUS.Visit.value().equals(myProject.getCompanyStatus())){
                if(!StringUtil.isEmpty(myProject.getFirstSource())){
                    dataPlanProjectService.updateKnockBackStatusById(myProject.getFirstSource());
                }
            }
            //流程插入新状态
            ProcessStatus processStatus = createNextStatus(myProject , userId);
            processStatusRepository.insert(processStatus);
        }else {
            logger.info("当前状态不支持下一步,id:{}",id);
        }

    }

    /**
     * 新建一个全新的状态
     * @param myProject
     * @return com.yunhe.merchants.domain.ProcessStatus
     * @create 2021/5/11 17:45
     */
    private ProcessStatus createNextStatus(MyProject myProject , Long userId) {
        ProcessStatus processStatusOld = processStatusRepository.selectByProjectIdAndStatus(myProject.getId(), String.valueOf(Integer.parseInt(myProject.getCompanyStatus()) - 1));
        ProcessStatus processStatus = new ProcessStatus();
        if(processStatusOld != null){
            BeanUtils.copyProperties(processStatusOld,processStatus);
            processStatus.setId(null);
        }
        processStatus.setStatus(myProject.getCompanyStatus());
        processStatus.setProjectId(myProject.getId());
        processStatus.setPrincipal(userId);
        processStatus.setOrgId(getOrgId(userId));
        return processStatus;
    }

    /**
     * 流程失败
     * @return com.yunhe.merchants.domain.ProcessStatus
     * @create 2021/5/11 17:45
     */
    private void failStatus(ProcessStatus processStatus) {
        processStatus.setStatus(MyProjectConsts.COMPANY_STATUS.Fail.value());
    }
    private Long getOrgId(Long userId){
        String orgIdStr = redisClient.get("Org:" + userId);
        if (!StringUtil.isEmpty(orgIdStr)){
            return Long.parseLong(orgIdStr.split("-")[0]);
        }else {
            return null;
        }

    }


}
